# -*- coding: utf-8 -*-

"""
@Remark: 自定义异常处理
"""
import logging
import re
import traceback
from django.db.utils import DataError
from django.db.models import ProtectedError
from django.http import Http404
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
from rest_framework.views import set_rollback

from utils.custom_serializer_except import SerializerValidateError

# from utils.custom.exceptions import SerializerValidateError
# from utils.custom.json_response import ErrorResponse

logger = logging.getLogger(__name__)


from rest_framework.response import Response


class SuccessResponse(Response):
    """
    标准响应成功的返回, SuccessResponse(data)或者SuccessResponse(data=data)
    (1)默认code返回2000, 不支持指定其他返回码
    """

    def __init__(self, data=None, msg='success', status=None, template_name=None, headers=None, exception=False,
                 content_type=None, page=1, limit=1, total=1):
        std_data = {
            "code": 200,
            "msg": msg,
            "results": data,
            "count": total,
            "page": page,
            "limit": limit,
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


class DetailResponse(Response):
    """
    不包含分页信息的接口返回,主要用于单条数据查询
    (1)默认code返回2000, 不支持指定其他返回码
    """

    def __init__(self, data=None, msg='success', status=None, template_name=None, headers=None, exception=False,
                 content_type=None, ):
        std_data = {
            "code": 200,
            "msg": msg,
            "results": data,
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


class ErrorResponse(Response):
    """
    标准响应错误的返回,ErrorResponse(msg='xxx')
    (1)默认错误码返回400, 也可以指定其他返回码:ErrorResponse(code=xxx)
    """

    def __init__(self, data=None, msg='error', code=400, status=400, template_name=None, headers=None,
                 exception=False, content_type=None):
        std_data = {
            "success": False,
            "code": code,
            "message": msg,
            "results": data,
        }
        super().__init__(std_data, status, template_name, headers, exception, content_type)


def CustomExceptionHandler(ex, context):
    """
    统一异常拦截处理
    目的:(1)取消所有的500异常响应,统一响应为标准错误返回
        (2)准确显示错误信息
    :param ex:
    :param context:
    :return:
    """
    msg = ''
    code = 400

    if isinstance(ex, AuthenticationFailed):
        code = 401
        msg = ex.detail
    elif isinstance(ex, DRFAPIException):
        set_rollback()
        msg = ex.detail
    elif isinstance(ex, DataError):
        if len(ex.args) == 2:
            error_msg = ex.args[1]
            matched = re.fullmatch(r"^Out of range value for column '(\w+)' at row \d+$", error_msg)
            if matched:
                field = matched.groups()[0]
                msg = f"字段【{field}】超过最大数量限制！"
                return ErrorResponse(msg=msg, code=code)

        msg = str(ex)
        logger.error(traceback.format_exc())

    elif isinstance(ex, ProtectedError):
        set_rollback()
        msg = "删除失败:该条数据与其他数据有相关绑定"
    elif isinstance(ex, Http404):
        msg = "对象不存在或已删除！"
        code = 404
    elif isinstance(ex, SerializerValidateError):
        msg = ex.detail
        code = ex.code

    elif isinstance(ex, Exception):
        logger.error(traceback.format_exc())
        msg = str(ex)

    return ErrorResponse(msg=msg, code=code)
